package rate

import (
	"context"
	"engine/cache"
	"lib/db"
	"lib/log"
	"lib/notice"
	"strconv"
)

type CurrencyMap struct {
	token              string
	v                  map[string]float64
	changeCurrencyList []string
}

func NewCurrencyMap(token string) *CurrencyMap {
	return &CurrencyMap{
		token: token,
		v:     make(map[string]float64, 21),
	}
}

func (cm *CurrencyMap) reset() {
	cm.changeCurrencyList = make([]string, 0, 21)
}

// 同步汇率
func (cm *CurrencyMap) Sync() map[string]float64 {
	cm.reset()
	getCnyRate()
	cm.saveRedis()

	if len(cm.changeCurrencyList) == 0 {
		return nil
	}

	changeCurrencyMap := make(map[string]float64, len(cm.changeCurrencyList))
	for _, currencyCode := range cm.changeCurrencyList {
		changeCurrencyMap[currencyCode] = cm.v[currencyCode]
	}
	return changeCurrencyMap
}

func (cm *CurrencyMap) setPreCurrencyRate(currencyName, rateStr string) {
	log.Infof("货币汇率：：%s-%s", currencyName, rateStr)
	code, ok := CurrencyName2Code[currencyName]
	if !ok {
		log.Errorf("未知的外币：：%s-%s", currencyName, rateStr)
		notice.SendWechatMsgf(cm.token, "未知的外币：%s-%s", currencyName, rateStr)
		return
	}

	rate, err := strconv.ParseFloat(rateStr, 64)
	if err != nil {
		log.Errorf("转换异常：[%s] - %v", rateStr, err)
		return
	}

	if r, ok := cm.v[code]; ok {
		if r == rate {
			return
		}

		if (rate-r)/r > 5 && (r-rate)/r > 5 {
			notice.SendWechatMsgf(cm.token, "汇率[%s]同步异常: 涨跌幅度较大,之前-%f，现在-%f", code, r, rate) // 发送企业微信
			return
		}
	}

	cm.v[code] = rate
	cm.changeCurrencyList = append(cm.changeCurrencyList, code)
}

func (cm *CurrencyMap) GetRate(currencyCode string) (float64, bool) {
	rate, ok := cm.v[currencyCode]
	return rate, ok
}

func (cm *CurrencyMap) get() map[string]any {
	ok := false
	tMap := make(map[string]any, len(cm.v))
	for k, v := range cm.v {
		tMap[k] = v
		ok = true
	}
	if !ok {
		return nil
	}
	return tMap
}

func (cm *CurrencyMap) saveRedis() {
	v := cm.get()
	if v == nil {
		return
	}
	err := db.GetRedisClient().HMSet(context.Background(), cache.GetCurrencyRateRedisKey(), v).Err()
	if err != nil {
		log.Errorf("缓存汇率失败：%v", err)
	}
}
